import axios from 'axios';
import Qs from 'qs';
import {MessagePlugin as Message, LoadingPlugin} from 'tdesign-vue';
import {saveAs} from 'file-saver';
import store from '@/store';
import router from '@/router';
import errorCode from '@/utils/errorCode'
import {getToken} from '@/utils/auth.js'
import {tansParams, blobValidate, tansParamsToObject} from "@/utils/common";
import { getSign } from "@/utils/sign";


// 是否显示重新登录
let isReLogin = false;
const pendingRequest = new Map();

function generateReqKey(config) {
  const {method, url, params, data} = config;
  return [method, url, Qs.stringify(params), Qs.stringify(data)].join(
    "&"
  );
}

function addPendingRequest(config) {
  const requestKey = generateReqKey(config);
  config.cancelToken =
    config.cancelToken ||
    new axios.CancelToken((cancel) => {
      if (!pendingRequest.has(requestKey)) {
        pendingRequest.set(requestKey, cancel);
      }
    });
}

function removePendingRequest(config) {
  const requestKey = generateReqKey(config);
  if (pendingRequest.has(requestKey)) {
    const cancel = pendingRequest.get(requestKey);
    cancel(requestKey);
    pendingRequest.delete(requestKey);
  }
}

const instance = axios.create({
  baseURL: import.meta.env.VITE_APP_BASE_API,
  timeout: 15000,
  // withCredentials: true,
  headers: {
    "Content-Type": "application/json;charset=UTF-8"
  },
});

instance.interceptors.request.use((config) => {
  if (config.method !== 'get' && !['/system/dict/data/types'].includes(config.url)) {
    removePendingRequest(config); // 检查是否存在重复请求，若存在则取消已发的请求
    addPendingRequest(config); // 把当前请求添加到pendingRequest对象中
  }
  if (config.method === 'get') {
    config.params = getSign(tansParamsToObject(config.params || {}) || {});
    let url = `${config.url}?${tansParams(config.params || {})}`;
    url = url.slice(0, -1);
    config.params = {};
    config.url = url;
  }else {
    config.data = getSign(config.data || {});
  }
  const token = getToken();
  if (token) {
    config.headers.Authorization = `Bearer ${token}`;
  }
  return config
});

instance.interceptors.response.use(
  (res) => {
    removePendingRequest(res.config); // 从pendingRequest对象中移除请求
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    let msg = errorCode[code.toString()] || res.data.msg || errorCode.default
    // 二进制数据则直接返回
    if (res.request.responseType === 'blob' || res.request.responseType === 'arraybuffer') {
      return res.data
    }
    if (code === 401) {
      if (!isReLogin) {
        isReLogin = true;
        store.dispatch('user/LogOut').then(() => {
          isReLogin = false;
          router.push('/login');
        }).catch(() => {
          store.dispatch('user/FedLogOut');
          isReLogin = false;
          router.push('/login');
        });
        // return Promise.reject(new Error("无效的会话，或者会话已过期，请重新登录。"))
        msg = "无效的会话，或者会话已过期，请重新登录。"
      }
    }
    if (code !== 200) {
      return Promise.reject(new Error(msg));
    }
    return res.data
  },
  (err) => {
    removePendingRequest(err.config || {}); // 从pendingRequest对象中移除请求
    // if (axios.isCancel(err)) {
    //   console.log(`已取消的重复请求：${  err}`);
    // } else {
    //   // 添加异常处理
    // }
    let {message} = err;
    if (message === "Network Error") {
      message = "后端接口连接异常";
    } else if (message.includes("timeout")) {
      message = "系统接口请求超时";
    } else if (message.includes("Request failed with status code")) {
      message = `系统接口${message.slice(message.length - 3)}异常`;
    } else if (err.code.includes("ERR_CANCELED")) {
      message = "禁止重复请求";
    }
    return Promise.reject(message);
  },
);


// 通用下载方法
export function download(url, params, filename) {
  const loadingInstance = LoadingPlugin({
    fullscreen: true,
    attach: 'body',
    preventScrollThrough: false,
    text: "正在下载数据，请稍候"
  });
  return instance.get(url, {params, responseType: 'arraybuffer', timeout: 0}).then(async (data) => {
    const blob = new Blob([data], {type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'})
    saveAs(blob, filename)
    loadingInstance.hide();
  }).catch((r) => {
    console.error(r)
    Message.error('下载文件出现错误，请联系管理员！')
    loadingInstance.hide();
  })
}

export default instance;
